package com.jisf.driver.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jisf.driver.entity.enumtype.StageEnum;
import com.jisf.driver.entity.enumtype.SubjectEnum;
import com.jisf.driver.entity.po.DrivingSchoolLog;
import com.jisf.driver.entity.po.Examine;
import com.jisf.driver.entity.vo.ExamineListRequestVo;
import com.jisf.driver.entity.vo.ExamineListResponseVo;
import com.jisf.driver.entity.vo.ExamineVo;
import com.jisf.driver.entity.vo.StudentExamineResponseVo;
import com.jisf.driver.exception.DrivingSchoolException;
import com.jisf.driver.exception.SystemException;
import com.jisf.driver.mapper.ExamineMapper;
import com.jisf.driver.response.ResultCode;
import com.jisf.driver.service.ICoachService;
import com.jisf.driver.service.IExamineService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jisf.driver.utils.DateUtil;
import com.jisf.driver.utils.LogUtil;
import com.jisf.driver.utils.UserUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author jisf
 * @since 2022-05-10
 */
@Service
public class ExamineServiceImpl extends ServiceImpl<ExamineMapper, Examine> implements IExamineService {

    @Autowired
    private ExamineMapper examineMapper;

    @Autowired
    private LogUtil log;

    /**
     * 获取考试列表
     *
     * @param examineListRequestVo
     * @return
     */
    @Override
    public ExamineListResponseVo getExamineList(ExamineListRequestVo examineListRequestVo) {
        try {
            QueryWrapper<Examine> queryWrapper = new QueryWrapper<>();
            String subject = examineListRequestVo.getSubject();
            if (StringUtils.isNotBlank(subject)) {
                queryWrapper.eq("subject", Objects.requireNonNull(SubjectEnum.getEnum(subject)).getCode());
            }
            String stage = examineListRequestVo.getStage();
            if (StringUtils.isNotBlank(stage)) {
                queryWrapper.eq("stage", Objects.requireNonNull(StageEnum.getEnum(stage)).getCode());
            }
            String dateStr = examineListRequestVo.getDate();
            if (StringUtils.isNotBlank(dateStr)) {
                Date date = DateUtil.YearToDay.parse(dateStr);
                if (ObjectUtils.isNotNull(date)) {
                    queryWrapper.eq("date", date);
                }
            }

            queryWrapper.orderByDesc("date");
            Page<Examine> page = new Page<>(examineListRequestVo.getPage(), examineListRequestVo.getSize());
            Page<Examine> examinePage = examineMapper.selectPage(page, queryWrapper);
            ExamineListResponseVo examineListResponseVo = new ExamineListResponseVo();
            examineListResponseVo.setTotal(examinePage.getTotal());
            examineListResponseVo.setExamineList(examinePage.getRecords());
            return examineListResponseVo;
        } catch (ParseException e) {
            throw new DrivingSchoolException("日期格式异常", e);
        } catch (Exception e){
            throw new SystemException(e);
        }
    }

    /**
     * 获取已预约考试列表
     * @return
     */
    @Override
    public List<StudentExamineResponseVo> getExamineAppointList() {
        try {
            Integer userid = UserUtil.userIdThreadLocal.get();
            return examineMapper.getExamineAppointList(userid);
        }catch (Exception e){
            throw new SystemException(e);
        }
    }

    /**
     * 教练获取分配的考试列表
     * @return
     */
    @Override
    public List<Examine> getExamineAllotList() {
        try {
            Integer userid = UserUtil.userIdThreadLocal.get();
            return examineMapper.getExamineAllotList(userid);
        }catch (Exception e){
            throw new SystemException(e);
        }
    }

    /**
     * 新增考试
     *
     * @param examineVo
     * @return
     */
    @Override
    public ResultCode addExamine(ExamineVo examineVo) {
        try {
            Examine examine = new Examine();
            BeanUtils.copyProperties(examineVo, examine);
            examine.setDate(DateUtil.YearToDay.parse(examineVo.getDate()));
            examine.setAppointNumber(0);
            examine.setStage(StageEnum.APPLY_ING);
            examine.setPassNumber(0);
            int insert = examineMapper.insert(examine);

            // 存储日志
            String operator = UserUtil.usernameThreadLocal.get();
            String msg = String.format("用户名为%s的用户新增一门场次为%s的考试", operator, examine.getName());

            if (insert != 0){
                String drivingSchoolLog = JSONObject.toJSONString(new DrivingSchoolLog(operator, msg, true));
                log.info(drivingSchoolLog);
                return ResultCode.EXAMINE_ADD_SUCCESS;
            }else {
                String drivingSchoolLog = JSONObject.toJSONString(new DrivingSchoolLog(operator, msg, false));
                log.info(drivingSchoolLog);
                return ResultCode.EXAMINE_ADD_FAILED;
            }
        }catch (ParseException e){
            throw new DrivingSchoolException("日期格式异常", e);
        }catch (Exception e){
            throw new SystemException(e);
        }
    }

    /**
     * 更新考试状态
     */
    @Override
    public void updateExamineStage() {
        try {
            QueryWrapper<Examine> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("stage", 1)
                    .or().eq("stage", 2)
                    .or().eq("stage", 3);
            List<Examine> examines = examineMapper.selectList(queryWrapper);

            long time = new Date().getTime() + 1000 * 3600L * 24;
            Date today = DateUtil.YearToDay.parse(DateUtil.YearToDay.format(new Date()));
            Date tomorrow = DateUtil.YearToDay.parse(DateUtil.YearToDay.format(new Date(time)));

            for (Examine examine : examines) {
                Date date = examine.getDate();
                if (today.after(date)) {
                    examine.setStage(StageEnum.EXAMINE_END);
                } else if (tomorrow.after(date)) {
                    examine.setStage(StageEnum.EXAMINE_ING);
                } else if (!tomorrow.before(date)) {
                    examine.setStage(StageEnum.APPLE_END);
                } else {
                    continue;
                }
                int update = examineMapper.updateById(examine);
                if (update != 0) {
                    String msg = String.format("id为%d的考试状态更改为%s", examine.getId(), examine.getStage().getName());
                    String drivingSchoolLog = JSONObject.toJSONString(new DrivingSchoolLog("系统消息", msg, true));
                    log.info(drivingSchoolLog);
                }
            }
        } catch (ParseException e) {
            throw new DrivingSchoolException("日期格式错误", e);
        } catch (Exception e) {
            throw new SystemException(e);
        }
    }

    /**
     * 结束报名
     *
     * @param id
     * @return
     */
    @Override
    public ResultCode finishAppoint(Integer id) {
        try {
            Examine examine = new Examine();
            examine.setId(id);
            examine.setStage(StageEnum.APPLE_END);
            int update = examineMapper.updateById(examine);

            // 存储日志
            String operator = UserUtil.usernameThreadLocal.get();
            String examineName = examineMapper.selectById(id).getName();
            String msg = String.format("用户名为%s的用户结束场次为%s的考试的报名", operator, examineName);

            if (update != 0){
                String drivingSchoolLog = JSONObject.toJSONString(new DrivingSchoolLog(operator, msg, true));
                log.info(drivingSchoolLog);
                return ResultCode.EXAMINE_FINISH_APPOINT_SUCCESS;
            }else {
                String drivingSchoolLog = JSONObject.toJSONString(new DrivingSchoolLog(operator, msg, false));
                log.info(drivingSchoolLog);
                return ResultCode.EXAMINE_FINISH_APPOINT_FAILED;
            }
        }catch (Exception e){
            throw new SystemException(e);
        }
    }


}
